<template>
  <div ref="popoverWrapRef" class="m-popover">
    <transition name="opacity">
      <Tooltip
        v-if="showTooltip"
        :placement="placement"
        :width="width"
        @clickout="clickTooltipOut"
      >
        <slot name="popover" />
      </Tooltip>
    </transition>
  </div>
</template>

<script lang="ts">
import useCreateAPI from "/@/m-ui/hooks/useCreateApi";
import {
  computed,
  defineComponent,
  onMounted,
  onUnmounted,
  PropType,
  ref,
  watch,
} from "vue";
import Tooltip from "./Tooltip.vue";
import type { PopoverPlacement, PopoverTrigger } from "./types";
import { useClickAway } from "@vant/use";
export default defineComponent({
  name: "MPopover",
  props: {
    // 	popover 的弹出位置
    placement: {
      type: String as PropType<PopoverPlacement>,
      default: "top",
    },
    // popover 的触发方式
    trigger: {
      type: String as PropType<PopoverTrigger>,
      default: "hover",
    },
    // 悬浮触发弹出信息的延迟
    delay: {
      type: Number,
      default: 100,
    },
    // 悬浮关闭弹出信息的延迟
    duration: {
      type: Number,
      default: 100,
    },
    show: {
      type: Boolean,
      default: () => undefined,
    },
    width: {
      type: [Number, String],
      default: "",
    },
    outClose: {
      type: Boolean,
      default: true,
    },
  },
  components: {
    Tooltip,
  },
  emits: ["change"],
  setup(props, { emit, slots }) {
    const popoverWrapRef = ref();
    const apeendElRef = ref<Element>();

    const _showTooltip = ref(false);
    const showTooltip = computed(() => {
      if (props.show != undefined) {
        return props.show;
      } else {
        return _showTooltip.value;
      }
    });

    const handleShow = () => {
      _showTooltip.value = true;
      emit("change", _showTooltip.value);
    };
    const handleHidden = () => {
      _showTooltip.value = false;
      emit("change", _showTooltip.value);
    };

    const handleMouseenter = () => {
      handleShow();
    };

    const handleClick = () => {
      _showTooltip.value = !_showTooltip.value;
      emit("change", _showTooltip.value);
    };

    const handleMouseleave = () => {
      handleHidden();
    };
    const handleFocus = () => {
      handleShow();
    };
    const handleBlur = () => {
      handleHidden();
    };

    const removeEventListener = () => {
      if (apeendElRef.value) {
        apeendElRef.value.removeEventListener("mouseenter", handleMouseenter);
        apeendElRef.value.removeEventListener("mouseleave", handleMouseleave);
        apeendElRef.value.removeEventListener("click", handleClick);
        apeendElRef.value.removeEventListener("focus", handleFocus);
        apeendElRef.value.removeEventListener("blur", handleBlur);
      }
    };

    const addEventListener = (el?: Element) => {
      // 自定义控制,不绑定
      if (props.show != undefined) {
        return;
      }
      if (!el) {
        el = apeendElRef.value;
      }
      if (props.trigger === "hover") {
        el.addEventListener("mouseenter", handleMouseenter);
        el.addEventListener("mouseleave", handleMouseleave);
      } else if (props.trigger === "click") {
        el.addEventListener("click", handleClick);
      } else if (props.trigger === "focus") {
        el.addEventListener("focus", handleFocus);
        el.addEventListener("blur", handleBlur);
      }
    };

    const clickTooltipOut = () => {
      // 不开启outClose
      if (!props.outClose) {
        return;
      }
      // 自定义控制
      if (props.show != undefined) {
        return;
      }

      // 没开启
      if (!_showTooltip.value) {
        return;
      }
      console.log("点击外界--关闭");
      handleHidden();
    };

    onUnmounted(() => {
      removeEventListener();
    });

    const initPopover = () => {
      if (!slots.default) {
        return false;
      }
      const { el } = useCreateAPI(slots.default()[0], {}, popoverWrapRef.value);
      apeendElRef.value = el;
      // 自定义控制不绑定

      addEventListener(el);
    };

    onMounted(() => {
      initPopover();
    });
    // 改变了触发方式,重新绑定事件
    watch(props, (newVal, oldVal) => {
      if (newVal.trigger !== oldVal.trigger) {
        removeEventListener();
        addEventListener();
      }
    });

    useClickAway(popoverWrapRef, (e) => {
      clickTooltipOut();
    });

    return {
      popoverWrapRef,
      showTooltip,
      clickTooltipOut,
    };
  },
});
</script>
